Directive: v-something

<div id="app">
    <h1>{{ message }}</h1>
  	<input v-model="message" type="text">
</div>

<script>
    new Vue({
        el: '#app',
        data: {
            message: 'Hello World'
        }
    })
</script>

Often used directives:

  • v-model:双向绑定

  • v-if:从DOM树里删除/添加

  • v-show:增加class: disable

  • v-for:遍历,如 v-for="plan in plans"

  • v-on:events (or @events):绑定事件,如下 <form action="00.html" v-on:submit="handleIt"> events 包括click,hover,submit…

    • Event Modifier v-on:click.stop="…": event.stopPropagation(); v-on:submit.prevent="...": event.preventDefault();

    **在event 后面其实是一个方法,也可以是一个简单的表达式。表达式可以识别data中的变量。**如下: @click="count =+ 1"

    建议在Vue 里使用v-on 去绑定事件而不是在JS 中,因为这样JS 就可以专注业务,几乎不涉及DOM

Component

/*HTML*/
<div id="app">
    <my-counter title="Like"></my-counter>
    <my-counter title="Dislike"></my-counter>
</div>
/*Template*/
<template id="counterTemplate">
    <div>
        <span> {{ title }}: </span>
        <button @click="count++"> {{ count }} </button>
    </div>
</template>
/*Vue*/
<script>
    Vue.component('my-counter', {
        template: "#counterTemplate",
        data: function(){
            return {count: 0}
        },
        props: ['title']
    })

    var vm = new Vue({
        el: "#app"
    })
</script>
  • Component 可以全局,也可以local写在new Vue里面
  • Component 的数据一定要用function返回的形式表现
  • 不要忘记实例化Vue

单向数据传递

Vue2.0 严格实行数据单向传递,数据只能从parent 流向child,不能在child 里修改props.

  • 从Parent(Vue实例) 到Child(一般指component),以props 的形式进行
    • 绑定: v-bind or :
    • props: [’…’]
    • 传下来的变量,如果要用在computed 等方法里面,记得要加this
  • 从Child 到Parent,只能使用触发事件 (on & emit) 的方式
    • v-on 可以直接作用在component 上面
    • template 上 v-on:click 触发一个事件,事件里通过 this.$emit('example', data) 触发example事件
    • 在component 里面通过 v-on:example 触发事件,在回调函数里接收 data

Computed vs Watch

<div id="app">
    <p>Your Level: {{ level }}</p><br>
    <button @click="points += 10">kill enermy</button>
    <p>Experience: {{ points }}<p></p>
</div>

<script>
    var vm = new Vue({
        el: "#app",
        data: {
            points: 0
        },
        //in fact, watch can do the same thing.
        //in most case, computed is prefered
        computed: {
            level: function(){
                if(this.points <= 20) return 1;
                if(this.points <= 50) return 2;
                if(this.points <= 100) return 3;
                if(this.points <= 150) return 4;
                return "MAX";
            }
        }
    })

Class

<div :class={active: isActive, error: hasError}: 如果isActive 属性为真,增加active 类;如果hasError 为真,增加error类。

或者:

<div :class=[activeClass, errorClass]></div>
<script>
  ...
  data: {
 	 	activeClass: 'active',
  		errorClass: 'text-danger'
  		}
</script>

Utils (Mixin)

如果有一些通用的Utils 方法或变量,可以通过Mixin 方法全局调用,如下

Vue.mixin({
  methods: {
    method1 () {
      // do something
    }
  }
})

// in the component .vue 
// simply use
... this.method1

Webpack

使用Notes\vue_learn\webpack+vue 里的配置 npm install; npm upadte 入口为src/main.js,基本模版为src/components/app.vue,出口为dist/main.js 利用webpack-dev-server -inline 进行live-load 详细内容见 webpack.md

  • 在index.html 中引入bundle 文件和基本div

    <div id="app"></div>
    <script src="dist/main.js"></script>
    
  • 在入口文件 main.js 中引入Vue 和 基本模版app

    import Vue from "vue";
    import app from "./components/app";
    Vue.config.debug = true;
    new Vue(app);
    
  • 基本模版 app.vue 是编写网站的基础,所有的组件tag 都是用在这里面,例如

 <script>
    import hello from './hello.vue';	//引入组件
    import list from './list.vue';		//引入组件
    export default {					//ES6默认导出
        el: "#app",						//band to #app in index.html 唯一接口
        data: function () {				//data,可以用ES6 写成 data () {}
            return {
                name: "Ethan",
                age: 24
            }
        },
        components: {					//所有组件需要在这里注册才能使用
            hello,
            list
        }
    }
</script>

<template>								//HTML 页面一样的写法
    <div>
        <h1>Name: {{ name }}</h1>
        <h1>Age: {{ age }}</h1>
        <hello></hello>					//直接使用模版tag
        <list></list>
    </div>
</template>

<style lang="sass" rel="stylesheet/scss">	//CSS 使用SCSS 预编译
  $qwe: blue;

  body {
      background-color: $qwe;
      h1:hover {
          height: 100px;
      }
      h2 {
          background-color: #999;
      }
  }
</style> 
  • 其中的Hello 和List 都是组件,在./src/conponents/hello.vue 和 list.vue 中,例如 list.vue
<script>
    export default{							//默认导出
        data: function () {					//直接写data,不需要el绑定
            return {
                lists: [
                {name: "小红",age: 20}, 
                {name: "张三",age: 12}]
            }
        }
    }
</script>

<template>
    <div>
        <ul>
            <li v-for="item in lists">				//正常vue directive 用法
                <h3 class="name">NAME: {{ item.name }}</h3>
                <h3 class="age">AGE: {{ item.age }}</h3>
            </li>
        </ul>
    </div>
</template>

<style lang="sass" rel="stylesheet/scss">
...
</style>

Laravel

blade

因为blade 也用{{}} 模版,和Vue 有冲突,所以需要在Vue 的模版符号前加上@,如@

  • 注意传来的JSON数据有可能需要用 JSON.parse() 解析一遍
  • 使用Ajax 的时候,建议在created 函数里进行请求,并且把数据赋予对应的data
  • 可以用jQuery请求Ajax,也可以用Vue-Resource 进行请求,非常方便

Filter

{{ msg | capitalize }} msg 全部大写

还有orderBy 功能,可以在v-for 的时候自动按照某一个属性进行排列limit-by

全部替换成javascript 在computed 中操作数据,如slice, lodash.orderby 等等

过滤器可以串联:

{{ message | filterA | filterB }} 过滤器是 JavaScript 函数,因此可以接受参数:{{ message | filterA(‘arg1’, arg2) }}

最重要的一点,filter 可以自定义

Vue.filter('customizedFilter', function(value, otherArgs){
  ... 		//such as newValue = captilize(value)
  return newValue; 
})

Vuex

Flux 构架就像眼睛,你自然会知道什么时候需要它

—— Vuex Website

Vuex 解决了传统单项数据流在大型应用中难以处理各种关系的问题,主要包括以下两点:

  1. 多个 view 同时依赖于某一个状态
  2. 来自不同 view 的行为需要更改同一个状态

决定我尝试 Vuex 的具体实例就是,利用 Firebase 做登陆的时候,几乎每个业务组件都需要获取用户的登录状态和用户信息,从而在用户登入登出时发生响应。实现这一点有三个做法

  • 在每个组件里去调用 Firebase.auth 去查询用户的登录情况
  • 在 Root 组件里调用一次,然后通过 Props 传递给每一个子组件
  • 通过 Vuex 集中管理状态,这样每个组件都可以通过 $states.currentUser 去查询信息

Store

Vuex 的核心就是 Store ,也叫做一个容器,它包含着应用中大部分的 State。Vuex 和全局对象有两点不同:

  1. Vuex 的状态存储是响应式的,如果 state 发生变化,所有使用它的 view 都会改变
  2. 你不能直接改变 store 里的状态。唯一的改变途径就是显示的提交 mutation,这样可以方便的跟踪每一个状态的变化。

Libraries

How not to include a library in a Vue.js project?

##Global Variable

entry.js

window._ = require('lodash')

component.vue

export default {
    created () {
        console.log(_.isEmpty() ? 'Lodash loaded' : 'Not really')
    }
}

Pros: easy to implement and use Cons: pollute global environment, not support server rendering

Import in every file

component…vue

import _ from 'lodash'
export default {
    created () {
        console.log(_.isEmpty() ? 'Lodash loaded' : 'Not really')
    }
}

Pros: it works Cons: not dry and just a pain to copy that everywhere. crazy for maintenance

Prototype

entry.js

import moment from 'moment';
Object.defineProperty(Vue.prototype, '$moment', {value: moment});

component.vue

export default {
    created () {
        console.log('The time is ' + this.$moment().format('HH:mm'));
    }
}

Pros: defineProperty defined property is read-only, $ make sure we follow the convention Cons: need a liitle bit more knowledge